﻿using MiddlewareTest.Middleware;
using MiddlewareTest.MiddlewareDelegate;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MiddlewareTest.AppBuilder
{
    public class ApplicationBuilder : IApplicationBuilder
    {
        private readonly List<Func<RequestDelegate, RequestDelegate>> _middlewares = new List<Func<RequestDelegate, RequestDelegate>>();
        private readonly IServiceProvider _serviceProvider;

        public ApplicationBuilder(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }

        public async Task<RequestContext> BuildAsync(RequestContext context)
        {
            var builder = this.Build();
            await builder(context);
            return context;
        }

        private RequestDelegate Build()
        {
            _middlewares.Reverse();
            return httpContext =>
            {
                RequestDelegate next = _ => { _.Response.StatusCode = 404; return Task.CompletedTask; };
                foreach (var middleware in _middlewares)
                {
                    next = middleware(next);
                }
                return next(httpContext);
            };
        }

        private IApplicationBuilder Use(Func<RequestDelegate, RequestDelegate> middleware)
        {
            _middlewares.Add(middleware);
            return this;
        }

        public IApplicationBuilder Use<T>() where T : BaseMiddleware
        {
            var obj = new object[] { _serviceProvider };
            var middlewareInstance = Activator.CreateInstance(typeof(T), obj) as BaseMiddleware;

            return Use(middlewareInstance.Invoke);
        }
    }
}
